import { mathFormulaApi } from '@/api/approvalModule.js';
import { initMathFormulaFunction } from './formulaMath';
import mathFun from '@/utils/math';
import axios from 'axios'; // 取消未完成请求

// 遍历处理自定义表单列表
/**
 *
 * @param {*} list 表单
 * @param {*} fn 处理方法
 * @param {*} subformKey 子表单key
 * @param {*} options 属性
 */
export const forEachFormOptions = (list, fn, options = {}) => {
  // options.notForEachSubform 不遍历子表单
  list.forEach(i => {
    if (options.subformKey) { // 如果是子表单里面的字段，则补充其所在子表单的key
      i.linkFormKey = options.subformKey;
      i.isSubTable = true;
    }
    if (fn) fn(i, options.subformKey, options.parentSubform);
    if (i.type === 'subform' && i.subform && !options.notForEachSubform) {
      forEachFormOptions(i.subform, fn, { subformKey: i.key, parentSubform: i });
    } else if (i.type === 'grid' && i.columns.length) {
      i.columns.forEach(j => {
        forEachFormOptions(j.list, fn);
      });
    }
  });
};
/**
 * 该节点是否为数值型字段
 * @param {*} element 节点
 * @returns
 */
export const isNumberType = (element) => {
  if (!element) return false;
  if ((element.type === 'input' && element.options && element.options.dataType === 'number') || (element.type === 'formulaInput' && !element.options.modeType) || element.type === 'statistics') {
    return true;
  }
  return false;
};

/**
 * 计算公式字段
 * @param {*} formOptions
 * @param {*} modifyElement 被修改的字段
 * @param {*} isTable 是否子表单字段
 */
let formulaCancelToken = null;
export const mathFormula = (formOptions, modifyElement, isTable, immediate) => {
  const moduleId = formOptions.moduleId;
  const processId = formOptions.processId || '';
  let formValue = null;
  let formValueTypes = null;

  if (!moduleId) return;
  const keyToFormula = formOptions.config.keyToFormula;
  if (!immediate && (!keyToFormula || Object.keys(keyToFormula).length === 0)) {
    // 如果没有任何引用关系，则判断如果是这个子表单里面存在公式字段，则计算一次
    // 因为有可能存在只有纯数值计算的公式
    let hasFormulaInput = false;
    if (modifyElement && modifyElement.key && modifyElement.type === 'subform') {
      hasFormulaInput = modifyElement.subform.some(i => i.type === 'formulaInput' && i.options && !i.options.modeType);
    }
    if (!hasFormulaInput) return;
  }
  let key = modifyElement.key || '';
  if (formValue && modifyElement.isSubTable && modifyElement.linkFormKey) {
    key = modifyElement.linkFormKey;
  }

  formValue = {};
  formValueTypes = {};
  forEachFormOptions(formOptions.list, (element) => {
    // 使子表单里面的数字字段的值变为 number 类型
    if (element.type === 'subform') {
      const numberKeys = [];
      element.subform.forEach(i => {
        const _isShowSecret = i.options && i.options.isSecret && i._isShowSecret;
        if (isNumberType(i) && _isShowSecret || (i.type === 'date' && !i.options.isRange)) {
          numberKeys.push(i.key);
        }
        formValueTypes[i.key] = isNumberType(i) && i.type !== 'formulaInput' ? 'number' : i.type;
      });
      if (element.value) {
        element.value.forEach(i => {
          numberKeys.forEach(numKey => {
            if (i[numKey]) i[numKey] = Number(i[numKey]);
          });
        });
      }
    }

    if (!element.isSubTable && !['grid', 'title', 'formulaInput', 'titleExplain'].includes(element.type)) {
      let elementValue = element.value;
      if (element.type === 'input' && element.options.dataType === 'number' && element.options.isShowPercentage) {
        elementValue = mathFun.divide(Number(elementValue), 100);
      }
      if (element.type === 'linkForm' || element.type === 'subform') {
        elementValue = _.cloneDeep(element.value);
        elementValue.forEach(it => {
          element.subform.map(j => {
            const _isShowSecret = j.options && j.options.isSecret && j._isShowSecret;
            if (element.type === 'subform' && j.type === 'input' && j.options.dataType === 'number' && j.options.isShowPercentage && _isShowSecret) {
              it[j.key] = mathFun.divide(Number(it[j.key]), 100);
            }
          });
        });
      }
      formValue[element.key] = element.value && element.options && element.options.dataType === 'number' ? Number(elementValue) : elementValue;
    }
    formValueTypes[element.key] = isNumberType(element) && element.type !== 'formulaInput' ? 'number' : element.type;
  }, { notForEachSubform: true });

  if (immediate || modifyElement.isSubTable || isTable || keyToFormula[modifyElement.key] || modifyElement.type === 'subform' || modifyElement.type === 'linkForm') {
    const params = {
      formValue,
      types: formValueTypes,
      moduleId,
      processId: processId || '',
      key
    };
    if (formulaCancelToken) formulaCancelToken.cancel('cancel');
    const source = axios.CancelToken.source();// 用于取消请求
    formulaCancelToken = source;
    mathFormulaApi(params, source.token).then(res => {
      if (res.code === 200 && res.data && Object.keys(res.data).length) {
        forEachFormOptions(formOptions.list, (element, subformKey, parentSubform) => {
          if (res.data[element.key] || res.data[element.key] === 0) {
            const precision = element.options.precision;
            if (element.isSubTable) {
              parentSubform.value.forEach(i => {
                i[element.key] = handelValue(res.data[element.key][i._id], precision);
              });
            } else {
              element.value = handelValue(res.data[element.key], precision);
            }
            initMathFormulaFunction(formOptions, element);
          }
        });
      }
      formulaCancelToken = null;
    }).catch((e) => {
      formulaCancelToken = null;
      console.log(e);
    });
  }
};

function handelValue(val, precision) {
  if ((precision || precision === 0) && val) {
    return Number(Number(val).toFixed(precision));
  }
  return val;
}
